<template>
  <div>
    <!-- 文章详情内容部分 -->
    <div v-show="artObj.title !== undefined">
      <!-- Header 区域 -->
      <van-nav-bar fixed title="文章详情" left-arrow @click-left="$router.back()" />

      <!-- 文章信息区域 -->
      <div class="article-container">
        <!-- 文章标题 -->
        <h1 class="art-title">{{ artObj.title }}</h1>

        <!-- 用户信息 -->
        <van-cell center :title="artObj.aut_name" :label="$timeTo(artObj.pubdate)">
          <template #icon>
            <img :src="artObj.aut_photo" alt="" class="avatar">
          </template>
          <template #default>
            <div>
              <van-button v-if="artObj.is_followed" @click="followedFn(false)" type="info" size="mini"
              >已关注</van-button>
              <van-button v-else @click="followedFn(true)"  icon="plus" type="info" size="mini" plain>关注</van-button>
            </div>
          </template>
        </van-cell>

        <!-- 分割线 -->
        <van-divider></van-divider>

        <!-- 文章内容 -->
        <div class="art-content" v-html="artObj.content "></div>

        <!-- 分割线 -->
        <van-divider>End</van-divider>

        <!-- 点赞 -->
        <div class="like-box">
          <van-button v-if="artObj.attitude && artObj.attitude !== -1" icon="good-job" type="danger" size="small"  @click="attitudeFn(false)">已点赞</van-button>
          <van-button v-else icon="good-job-o" type="danger" plain size="small" @click="attitudeFn(true)" >点赞</van-button>
        </div>
      </div>

      <van-list
        v-model="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
      >
        <!-- 文章评论 -->
        <Comment :list="commentList"></Comment>
      </van-list>

      <!-- 发布评论 -->
      <!-- 底部添加评论区域 - 1 -->
      <div :class="commentShow ? 'art-cmt-container-1' : 'art-cmt-container-2'">
        <div class="add-cmt-box van-hairline--top" v-if="commentShow">
          <van-icon name="arrow-left" size="0.48rem" @click="$router.back()" />
          <div class="ipt-cmt-div" @click="commentShow = false">发表评论</div>
          <div class="icon-box">
              <van-badge :content="totalCount > 0 ? totalCount : '' " max="99">
                  <van-icon @click="lookComFn" name="comment-o" size="0.53333333rem" />
              </van-badge>
              <van-icon name="star-o" size="0.53333333rem" />
              <van-icon name="share-o" size="0.53333333rem" />
          </div>
        </div>

        <!-- 底部添加评论区域 - 2 -->
        <div class="cmt-box van-hairline--top" v-else>
            <textarea v-model.trim="commentText" v-focus @blur="blurFn" placeholder="友善评论、理性发言、阳光心灵" ></textarea>
            <van-button type="default" :disabled="commentText.length === 0"
            @click="send">发布</van-button>
        </div>
      </div>
    </div>
    <!-- loading组件 -->
    <van-loading v-show="artObj.title === undefined" class="loading" type="spinner" vertical> 加载中...</van-loading>
  </div>
</template>

<script>
import { articleDetailAPI, followingsAPI, unFollowingsAPI, articleAttitudeAPI, unArticleAttitudeAPI, commentListAPI, sendCommentAPI } from '@/api'
import Comment from './Comment'
export default {
  data () {
    return {
      artObj: {}, // 文章详情的对象
      commentList: [], // 评论数据
      commentShow: true, // 底部发布评论组件的显示和隐藏
      totalCount: 0, // 评论总数量
      loading: false, // 底部加载中
      finished: false, // 是否全部加载完成
      lastId: null, // 下一页的评论数据从哪一个时间戳开始(要发给后台的参数)
      commentText: '' // 评论文本
    }
  },
  components: { Comment },
  methods: {
    // 目标: 点击发布按钮->执行点击事件方法
    // 现象: 一点击失去焦点, 整个下面发布评论的div都被移除DOM了, 造成点击事件无法执行
    // 解决: v-show取代v-if 或者 失去焦点事件设置v-if="commentShow" 的值为true, 晚一步执行
    // 代码: 用定时器把设置为true包起来(异步), setTimeout在所有代码(点击事件里代码都执行完毕), 才来执行setTimeout内的代码
    blurFn () {
      setTimeout(() => { // 异步回调
        this.commentShow = true // 先执行点击事件方法，再隐藏当前这一套div评论标签, 显示上一套的div评论标签
      }, 0)
    },
    async followedFn (bool) { // 关注 点击事件
      this.artObj.is_followed = bool
      if (bool === true) { // 要关注作者
        const [err] = await followingsAPI({
          target: this.artObj.aut_id // 作者id
        })
        // console.log(res)
        if (!err) this.$Toast({ message: '关注成功' })
      } else { // 取消关注作者
        const [err] = await unFollowingsAPI(this.artObj.aut_id)
        // console.log(err)
        if (!err) this.$Toast({ message: '取消关注成功' })
      }
    },
    async attitudeFn (bool) { // 文章点赞
      this.artObj.attitude = bool
      if (bool === true) { // 点赞文章
        const [err] = await articleAttitudeAPI({
          target: this.artObj.art_id // 文章id
        })
        if (!err) this.$Toast({ message: '点赞成功' })
      } else { // 取消点赞
        const [err] = await unArticleAttitudeAPI({ id: this.artObj.art_id })
        // const [err] = await unArticleAttitudeAPI(this.artObj.art_id)
        if (!err) this.$Toast({ message: '取消点赞成功' })
      }
    },
    async getCommentList () { // 请求：评论页数据
      const [, res] = await commentListAPI({
        type: 'a',
        // source: this.artObj.art_id
        source: this.$route.params.a_id, // 换成路由上的id
        offset: this.lastId // 如果传null给axios,axios会自动忽略当前key和value(不携带)
      })
      // console.log(res)
      if (res?.data?.data?.results.length === 0) {
        this.finished = true // 没有更多数据
      }
      this.commentList = [...this.commentList, ...res.data.data.results] // 累加数据，新数据拼接在旧数据后
      this.totalCount = res.data.data.total_count
      this.lastId = res.data.data.last_id // 保存每次的last_id,每次回来新的数据都得保存，为了下次做偏移请求下一页数据
      this.loading = false // 数据请求成功，底部加载中暂时关闭，保证van-list触底能正常再次触发onLoad事件
    },
    async send () { // 发表评论
      // console.log(this.commentText)
      const [, res] = await sendCommentAPI({
        target: this.$route.params.a_id,
        content: this.commentText
      })
      // console.log(res)
      this.commentList.unshift(res.data.data.new_obj)
      this.totalCount++ // 小微标数据+1
      this.commentText = '' // 清空文本数据
    },
    lookComFn () { // 点击 -- 显示评论区顶端
      // 1. 点击直接滚动过去
      // 思路：window.scrollTo 设置Y轴滚动值，滚动值就是文章内容的高度
      // window.scrollTo(x坐标，y坐标) -- 把滚动条滚动到指定位置(左上角位置 0 0)
      // window.scrollTo(0, document.querySelector('.article-container').offsetHeight)

      // 2. 点击滚动带动画(JS动画)
      // const now = window.scrollY // 当前窗口已经滚动出去的Y值
      // const dist = document.querySelector('.article-container').offsetHeight // 文章高度，就是要滚动出去的距离
      // const step = dist / 10 // 步长(一次滚动出去的距离)

      // setTimeout(() => {
      //   if (now + step > dist) { // 滚动出去的距离 + 步长 > 文章高度时
      //     return // 结束滚动，停止递归调用
      //   }
      //   window.scrollTo(0, now + step) // 滚动到(位置)：上一次滚出的距离(位置) + 本次要滚动的距离
      //   this.lookComFn() // 递归调用
      // }, 300)

      // 3. 缓冲动画 先快后慢
      // const now = window.scrollY // 文档在垂直方向已滚动的像素值
      // const dist = document.querySelector('.article-container').offsetHeight // 文章高度，就是要滚动出去的目标距离
      // const step = (dist - now) / 10 // 剩余要走的值/10 (10可以随便写, 但是10左右效果最好的) - 剩余要走的这次步长
      // 第一次now: 0, dist: 1000, step: 100
      // 第二次now: 100, dist:1000, step: 90
      // 第三次now: 190, dist:1000, step: 81
      // .......  step: 0.6 一直不动了
      // console.log(step)
      // setTimeout(() => {
      // if (now + step > dist) { // 这个判断存在误差，now + step 一直小于dist，就会一直递归调用
      //   if (step < 1) { // 判断是否滚动结束
      //     window.scrollTo(0, dist) // 动画停止，因为有误差，所以最后把文章高度设置为卷入的值(精度对准)
      //     return
      //   }
      //   window.scrollTo(0, now + step) // 滚动到：上一次滚出的距离 + 本次要滚动的距离
      //   this.lookComFn() // 递归调用
      // }, 30)

      // 4. 缓冲动画 先快后慢 从下往上滚动
      // const now = window.scrollY // 文档在垂直方向已滚动的像素值
      // const dist = document.querySelector('.article-container').offsetHeight // 目标：滚动距离,文章高度
      // const step = (dist - now) / 10 // 剩余要走的值 / 10
      // // console.log(step)
      // setTimeout(() => {
      //   // 当 now的距离大于 dist距离时，step步长是负数，now + step 一直小于dist，就会一直递归调用
      //   // if (now + step > dist) {
      //   if (Math.abs(step) < 1) { // 迈不动小于1停止
      //     window.scrollTo(0, dist)
      //     return
      //   }
      //   window.scrollTo(0, now + step) // 滚动到：上一次滚出的距离 + 本次要滚动的距离
      //   this.lookComFn() // 递归调用
      // }, 30)

      // 5. 无评论 文章足够长 文章id:23626
      // (重要): window.scrollTo(), y值无论设置多少，都不会让网页留白
      // 1.1 文档在垂直方向已滚动的像素值
      const now = window.scrollY
      // 1.2 目标：滚动出去的距离（文章信息区域的高度）
      let dist = document.querySelector('.article-container').offsetHeight
      // 1.3 可滚动高度 = 整个文档的高度 - 浏览器窗口的视口（viewport）高度
      const avalibleHeight = document.documentElement.scrollHeight - window.innerHeight
      // 2.1 如果【目标高度】 大于 【可滚动的高度】
      if (dist > avalibleHeight) {
        // 2.2 就把目标高度，设置为可滚动的高度
        dist = avalibleHeight
      }
      // 3. 动态计算出步长值
      const step = (dist - now) / 10 // 剩余要走的值 / 10
      setTimeout(() => {
        // 4.2 如果当前的滚动的距离不大于 1px，则直接滚动到目标位置，并退出递归
        if (Math.abs(step) < 1) {
          window.scrollTo(0, dist) // 因为有误差，所以最后把卷入的值设置为文章高度(精度对准)
          return
        }
        // 4.1 每隔 10ms 执行一次滚动，并递归地进行下一次的滚动
        window.scrollTo(0, now + step) // 滚动到：上一次滚出的距离 + 本次要滚动的距离
        this.lookComFn() // 递归调用
      }, 30)
    },
    onLoad () { // 触底加载更多
      this.getCommentList()
    }
  },
  async created () { // 获取文章详情
    const [, res] = await articleDetailAPI(this.$route.params.a_id) // a_id 路由路径规则里定义的参数名
    // console.log(res)
    this.artObj = res.data.data
    // 总结:
    // 前端路由传参
    // router/index.js - 路由规则path: "/detail/:a_id"
    // 上一页ArticleItem.vue 点击跳转到这页，传过来文章id拼接在url后面 -> /detail/1390789
    // 这页Article/index.vue ($route.params.a_id)获取文章id 1390780取在了原地

    // 给后端传值
    // 后端要求我们也在axios的url路径上传值
    // 后端接口名: /v1_0/articles/:id  (这一块id没任何意义, 只是告诉你这里要传id值)
    // axios请求的时候: url: `/v1_0/articles/${id}`
    // this.getCommentList()
  }
}

</script>

<style scoped lang="less">
.article-container {
  padding: 10px;
  margin-top: 46px;
}
.art-title {
  font-size: 16px;
  font-weight: bold;
  margin: 10px 0;
}

.art-content {
  font-size: 12px;
  line-height: 24px;
  width: 100%;
  overflow-x: scroll;
  word-break: break-all;
}

.van-cell {
  padding: 5px 0;
  &::after {
    display: none;
  }
}

.avatar {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background-color: #f8f8f8;
  margin-right: 5px;
  border: none;
}

.like-box {
  display: flex;
  justify-content: center;
}

/*美化 - 文章详情 - 底部的评论页面 */
// 外层容器
.art-cmt-container-1 {
  padding-bottom: 46px;
}
.art-cmt-container-2 {
  padding-bottom: 80px;
}

// 发布评论的盒子 - 1
.add-cmt-box {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  box-sizing: border-box;
  background-color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 46px;
  line-height: 46px;
  padding-left: 10px;
  .ipt-cmt-div {
    flex: 1;
    border: 1px solid #efefef;
    border-radius: 15px;
    height: 30px;
    font-size: 12px;
    line-height: 30px;
    padding-left: 15px;
    margin-left: 10px;
    background-color: #f8f8f8;
  }
  .icon-box {
    width: 40%;
    display: flex;
    justify-content: space-evenly;
    line-height: 0;
  }
}

.child {
  width: 20px;
  height: 20px;
  background: #f2f3f5;
}

// 发布评论的盒子 - 2
.cmt-box {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 80px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  padding-left: 10px;
  box-sizing: border-box;
  background-color: white;
  textarea {
    flex: 1;
    height: 66%;
    border: 1px solid #efefef;
    background-color: #f8f8f8;
    resize: none;
    border-radius: 6px;
    padding: 5px;
  }
  .van-button {
    height: 100%;
    border: none;
  }
}

.loading {
  margin-top: 50px;
}
</style>
